/*
Copyright 2010-2011 CumulusCloud
http://cumuluscloud.cc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package dyndns;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.text.DateFormat;
import java.util.Date;
import java.util.Vector;

import javax.net.ssl.SSLSocketFactory;

import org.apache.commons.codec.binary.Base64;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import cumulusCloud.common.InformationPath;
import dyndns.tools.XML;

public class DyndnsConfig {
	public boolean enabled = false;
	public String ip;
	public String hostname;
	public String username;
	public String password;
	public Vector<String> status = new Vector<String>();
	static private DateFormat df = DateFormat.getDateTimeInstance();
	
	public void loadConfig() {
		if (!new File(InformationPath.getCloudAppsDataPath("DynDNS") + "config.xml").exists()) {
			return;
		}
		
		try {
			Document doc = XML.loadFromFile(InformationPath.getCloudAppsDataPath("DynDNS") + "config.xml");
			Element rootElement = doc.getDocumentElement();

			enabled = XML.getTextValue(rootElement, "enabled").equals("true");
			ip = XML.getTextValue(rootElement, "ip");
			username = XML.getTextValue(rootElement, "username");
			password = XML.getTextValue(rootElement, "password");
			hostname = XML.getTextValue(rootElement, "hostname");
			status = new Vector<String>();
			
			NodeList statusList = rootElement.getElementsByTagName("status");
			Element statusElement = (Element) statusList.item(0);
			NodeList entriesList = statusElement.getElementsByTagName("entry");
			for (int i=0; i < entriesList.getLength(); ++i) {
				Element nextEntry = (Element) entriesList.item(i);
				status.add(nextEntry.getTextContent());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void rollStatus(String stat) {
		status.add(stat);
		
		while (status.size() > 5) {
			status.remove(0);
		}
	}
	
	public void saveConfig() {
		try {
			Document doc = XML.createXmlDocument();
			
			Element rootElement = doc.createElement("host");
			doc.appendChild(rootElement);

			Element enabledElement = doc.createElement("enabled");
			enabledElement.appendChild(doc.createTextNode( enabled?"true":"false" ));
			rootElement.appendChild(enabledElement);
			
			Element ipElement = doc.createElement("ip");
			ipElement.appendChild(doc.createTextNode( (ip!=null)?ip:"" ));
			rootElement.appendChild(ipElement);
			
			Element hostnameElement = doc.createElement("hostname");
			hostnameElement.appendChild(doc.createTextNode( (hostname!=null)?hostname:"" ));
			rootElement.appendChild(hostnameElement);

			Element usernameElement = doc.createElement("username");
			usernameElement.appendChild(doc.createTextNode( (username!=null)?username:"" ));
			rootElement.appendChild(usernameElement);

			Element passwordElement = doc.createElement("password");
			passwordElement.appendChild(doc.createTextNode( (password!=null)?password:"" ));
			rootElement.appendChild(passwordElement);

			Element statusElement = doc.createElement("status");
			for (String stat:status) {
				Element entryElement = doc.createElement("entry");
				entryElement.appendChild(doc.createTextNode(stat));
				statusElement.appendChild(entryElement);
			}		
			rootElement.appendChild(statusElement);
			
			XML.saveToFile(doc, InformationPath.getCloudAppsDataPath("DynDNS") + "config.xml");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public String toString() {
		return 	"ip: " + ip +
				" hostname: " + hostname +
				" username: " + username;
	}

	public boolean UpdateDNS(String currentIP) {
		if ( (!enabled) || (hostname == null) || (username == null) || (password == null) )
			return false;
		
		if ( (ip != null) && (currentIP.equals(ip)) )
			return true;
		
		ip = currentIP;
		String stat = df.format(new Date()) + " Updating " + hostname + " with IP " + ip + " ";
		
		String result = "ERROR CONTACTING SERVICE";
		try {			
			String userPassword = username + ":" + password;
			String encoding = Base64.encodeBase64String(userPassword.getBytes());
			
			Socket socket = SSLSocketFactory.getDefault().createSocket("members.dyndns.org", 443);
			PrintWriter pw = new PrintWriter(socket.getOutputStream());
			pw.println("GET /nic/update?hostname=" + hostname + "&myip=" + ip + " HTTP/1.1");
			pw.println("User-Agent: CCDynDNS 0.1");
			pw.println("Host: members.dyndns.org");
			pw.println("Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2");
			pw.println("Authorization: Basic " + encoding);
			pw.println();
			pw.flush();
			
			BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			
			while ( !(br.readLine()).isEmpty()) {} // Skip the header 
			br.readLine(); // Skip the bytes number
			
			result = br.readLine();
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

		stat += "[" + result + "]";
		rollStatus(stat);
		saveConfig();
		
		if ( (result.startsWith("good")) || (result.startsWith("nochg")) ) {
			return true;
		}
		
		return false;
	}
}
